//-----------------------------------------------------------------------------
// 1. DRIVER SETUP - create driver object, midi ports and detection information
//-----------------------------------------------------------------------------

// get the api's entry point
var midiremote_api = require('midiremote_api_v1')

// create the device driver main object
var deviceDriver = midiremote_api.makeDeviceDriver('MIDIPLUS', 'XMax', 'Louis Wdey')

// create objects representing the hardware's MIDI ports
var midiInput = deviceDriver.mPorts.makeMidiInput()
var midiOutput = deviceDriver.mPorts.makeMidiOutput()

// define all possible namings the devices MIDI ports could have
// NOTE: Windows and MacOS handle port naming differently
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('X4 Max')
    .expectOutputNameEquals('X4 Max')
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('X6 Max')
    .expectOutputNameEquals('X6 Max')
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('X8 Max')
    .expectOutputNameEquals('X8 Max')

deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('X4 Max MIDI In')
    .expectOutputNameEquals('X4 Max MIDI Out')
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('X6 Max MIDI In')
    .expectOutputNameEquals('X6 Max MIDI Out')
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('X8 Max MIDI In')
    .expectOutputNameEquals('X8 Max MIDI Out')
//deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
//    .expectInputNameEquals('MIDIIN2 (X4 Max)')
//    .expectOutputNameEquals('MIDIOUT2 (X4 Max)')


/*-----------------------------------------------------------------------------------------------------------------------------*/
// 2. SURFACE LAYOUT - create control elements and midi bindings
/*-----------------------------------------------------------------------------------------------------------------------------*/
var aiKnob = deviceDriver.mSurface.makePushEncoder(0, 2, 6, 6)

aiKnob.mEncoderValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 85) // channel 0, cc 85
aiKnob.mPushValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 86) // channel 0, cc 86
var KnobIncr = deviceDriver.mSurface.makeCustomValueVariable('VarKnobIncr')
var KnobDecr = deviceDriver.mSurface.makeCustomValueVariable('VarKnobDecr')

/*-----------------------------------------------------------------------------------------------------------------------------*/



var knob1 = deviceDriver.mSurface.makeKnob(36, 1, 4, 4)
var knob2 = deviceDriver.mSurface.makeKnob(40, 1, 4, 4)
var knob3 = deviceDriver.mSurface.makeKnob(44, 1, 4, 4)
var knob4 = deviceDriver.mSurface.makeKnob(48, 1, 4, 4)
var knob5 = deviceDriver.mSurface.makeKnob(52, 1, 4, 4)
var knob6 = deviceDriver.mSurface.makeKnob(56, 1, 4, 4)
var knob7 = deviceDriver.mSurface.makeKnob(60, 1, 4, 4)
var knob8 = deviceDriver.mSurface.makeKnob(64, 1, 4, 4)

// bind midi ports to surface elements

knob1.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 106) // channel 0, cc 106

knob2.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 107) // channel 0, cc 107

knob3.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 108) // channel 0, cc 108

knob4.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 109) // channel 0, cc 109

knob5.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 110) // channel 0, cc 110

knob6.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 111) // channel 0, cc 111

knob7.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 112) // channel 0, cc 112

knob8.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 113) // channel 0, cc 113
/*-----------------------------------------------------------------------------------------------------------------------------*/
var faders = []
var fader1 = deviceDriver.mSurface.makeFader(130, 1, 2, 5)
faders.push(fader1)
var fader2 = deviceDriver.mSurface.makeFader(132, 1, 2, 5)
faders.push(fader2)
var fader3 = deviceDriver.mSurface.makeFader(134, 1, 2, 5)
faders.push(fader3)
var fader4 = deviceDriver.mSurface.makeFader(136, 1, 2, 5)
faders.push(fader4)
var fader5 = deviceDriver.mSurface.makeFader(138, 1, 2, 5)
faders.push(fader5)
var fader6 = deviceDriver.mSurface.makeFader(140, 1, 2, 5)
faders.push(fader6)
var fader7 = deviceDriver.mSurface.makeFader(142, 1, 2, 5)
faders.push(fader7)
var fader8 = deviceDriver.mSurface.makeFader(144, 1, 2, 5)
faders.push(fader8)

fader1.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 87) // channel 0, cc 87

fader2.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 88) 

fader3.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 89) 

fader4.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 90) 
fader5.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 102) 

fader6.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 103)

fader7.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 104)

fader8.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 105) 
/*-----------------------------------------------------------------------------------------------------------------------------*/

var transButton1 = deviceDriver.mSurface.makeButton(17, 3, 3, 2)
var transButton2 = deviceDriver.mSurface.makeButton(20, 3, 3, 2)
var transButton3 = deviceDriver.mSurface.makeButton(23, 3, 3, 2)
var transButton4 = deviceDriver.mSurface.makeButton(17, 5, 3, 2)
var transButton5 = deviceDriver.mSurface.makeButton(20, 5, 3, 2)
var transButton6 = deviceDriver.mSurface.makeButton(23, 5, 3, 2)

transButton1.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 114) // channel 0, cc 114

transButton2.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 115) // channel 0, cc 115

transButton3.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 116) // channel 0, cc 116

transButton4.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 117) // channel 0, cc 117

transButton5.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 118) // channel 0, cc 118

transButton6.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 119) // channel 0, cc 119
/*-----------------------------------------------------------------------------------------------------------------------------*/
var Button1 = deviceDriver.mSurface.makeButton(36, 5, 4, 2)
var Button2 = deviceDriver.mSurface.makeButton(40, 5, 4, 2)
var Button3 = deviceDriver.mSurface.makeButton(44, 5, 4, 2)
var Button4 = deviceDriver.mSurface.makeButton(48, 5, 4, 2)
var Button5 = deviceDriver.mSurface.makeButton(52, 5, 4, 2)
var Button6 = deviceDriver.mSurface.makeButton(56, 5, 4, 2)
var Button7 = deviceDriver.mSurface.makeButton(60, 5, 4, 2)
var Button8 = deviceDriver.mSurface.makeButton(64, 5, 4, 2)

Button1.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 24) // channel 0, cc 24

Button2.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 25)

Button3.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 26)

Button4.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 27)
Button5.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 28)

Button6.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 29)

Button7.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 30)

Button8.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 31) 
/*-----------------------------------------------------------------------------------------------------------------------------*/
// 3. HOST MAPPING - create mapping pages and host bindings
/*-----------------------------------------------------------------------------------------------------------------------------*/

// create at least one mapping page
var page = deviceDriver.mMapping.makePage('Page1')
// create host accessing objects
var hostSelectedTrackChannel = page.mHostAccess.mTrackSelection.mMixerChannel
// bind surface elements to host accessing object values

//page.makeValueBinding(knob1.mSurfaceValue, hostSelectedTrackChannel.mValue.mVolume)
page.makeValueBinding(knob1.mSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(0))
page.makeValueBinding(knob2.mSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(1))
page.makeValueBinding(knob3.mSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(2))
page.makeValueBinding(knob4.mSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(3))
page.makeValueBinding(knob5.mSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(4))
page.makeValueBinding(knob6.mSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(5))
page.makeValueBinding(knob7.mSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(6))
page.makeValueBinding(knob8.mSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(7))

/*-----------------------------------------------------------------------------------------------------------------------------*/

//page.makeValueBinding(fader1.mSurfaceValue, hostSelectedTrackChannel.mValue.mVolume)
var hostMixerBankZone = page.mHostAccess.mMixConsole.makeMixerBankZone()
    .excludeInputChannels()
    .excludeOutputChannels()

for (var channelIndex = 0; channelIndex < 8; ++channelIndex) {
    var hostMixerBankChannel = hostMixerBankZone.makeMixerBankChannel()
    var faderSurfaceValue = faders[channelIndex].mSurfaceValue;
    page.makeValueBinding(faderSurfaceValue, hostMixerBankChannel.mValue.mVolume)

}
/*-----------------------------------------------------------------------------------------------------------------------------*/
aiKnob.mEncoderValue.mOnProcessValueChange = function (context, value) {
    //console.log(value.toString())
    if (value < 0.5) {
        KnobDecr.setProcessValue(context, 1.)
        KnobDecr.setProcessValue(context, 0.)

    }
    else if (value > 0.5) {
        KnobIncr.setProcessValue(context, 1.)
        KnobIncr.setProcessValue(context, 0.)
    }
}
page.makeActionBinding(KnobDecr, page.mHostAccess.mTrackSelection.mAction.mPrevTrack)
page.makeActionBinding(KnobIncr, page.mHostAccess.mTrackSelection.mAction.mNextTrack)
page.makeValueBinding(aiKnob.mPushValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mInstrumentOpen).setTypeToggle()
/*-----------------------------------------------------------------------------------------------------------------------------*/
//var g_timeline_is_displayed = false
//aiKnob.mEncoderValue.mOnProcessValueChange = function (context, value) {
//    //console.log(value.toString())
//    if (value < 0.5) {
//        KnobDecr.setProcessValue(context, 1.)
//        g_timeline_is_displayed = true

//    }
//    else if (value > 0.5) {
//        KnobIncr.setProcessValue(context, 1.)
//        g_timeline_is_displayed = true

//    }
//}
//page.makeCommandBinding(KnobDecr, 'Transport', 'Nudge Cursor Left')
//page.makeCommandBinding(KnobIncr, 'Transport', 'Nudge Cursor Right')
/*-----------------------------------------------------------------------------------------------------------------------------*/
page.makeValueBinding(transButton1.mSurfaceValue, page.mHostAccess.mTransport.mValue.mRewind)
page.makeValueBinding(transButton2.mSurfaceValue, page.mHostAccess.mTransport.mValue.mForward)
page.makeValueBinding(transButton3.mSurfaceValue, page.mHostAccess.mTransport.mValue.mCycleActive).setTypeToggle()
page.makeValueBinding(transButton4.mSurfaceValue, page.mHostAccess.mTransport.mValue.mRecord).setTypeToggle()
page.makeValueBinding(transButton5.mSurfaceValue, page.mHostAccess.mTransport.mValue.mStart).setTypeToggle()
page.makeValueBinding(transButton6.mSurfaceValue, page.mHostAccess.mTransport.mValue.mStop).setTypeToggle()
/*-----------------------------------------------------------------------------------------------------------------------------*/
page.makeCommandBinding(Button1.mSurfaceValue, 'Edit', 'Undo')
page.makeCommandBinding(Button2.mSurfaceValue, 'Edit', 'Redo')
page.makeValueBinding(Button3.mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mSolo).setTypeToggle()
page.makeValueBinding(Button4.mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mMute).setTypeToggle()
page.makeValueBinding(Button5.mSurfaceValue, page.mHostAccess.mTransport.mValue.mMetronomeActive).setTypeToggle()
/*page.makeValueBinding(Button6.mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mEditorOpen).setTypeToggle()*/
page.makeCommandBinding(Button6.mSurfaceValue, 'Devices', 'Mixer')
page.makeCommandBinding(Button7.mSurfaceValue, 'File', 'Export Audio Mixdown')
page.makeCommandBinding(Button8.mSurfaceValue, 'File', 'Save')
/*-----------------------------------------------------------------------------------------------------------------------------*/

deviceDriver.mOnDeactivate = function (context) {
    //console.log("DEINIT")
    
    DAWDisonnect(midiOutput, context)
    
}

function DAWDisonnect(midiOutput, context) {
    //console.log("DAW Disconnected")
    //metronme
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x1c, 0x00, 0xf7])
/*    midiOutput.sendMidi(context, [ 0x0b, 0xb0, 0x1c, 0x00])*/

    //rewind
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x72, 0x00, 0xf7])
    //fastforward
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x73, 0x00, 0xf7])
    //cycle
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x74, 0x00, 0xf7])
    //record
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x75, 0x00, 0xf7])
    //play
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x76, 0x00, 0xf7])
    //stop
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x77, 0x00, 0xf7])
    //solo
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x1a, 0x00, 0xf7])
    //mute
    midiOutput.sendMidi(context, [0xf0, 0x00, 0x21, 0x4e, 0x7f, 0x0b, 0xb0, 0x1b, 0x00, 0xf7])
}
/*-----------------------------------------------------------------------------------------------------------------------------*/


deviceDriver.mSurface.makePianoKeys(5, 8, 150, 15, 0, 86)//pianoUI

deviceDriver.mSurface.makePitchBend(0, 11, 2, 9)
deviceDriver.mSurface.makeModWheel(3, 11, 2, 9)
//6 tansport button
//deviceDriver.mSurface.makeButton(17, 3, 3, 2)
//deviceDriver.mSurface.makeButton(20, 3, 3, 2)
//deviceDriver.mSurface.makeButton(23, 3, 3, 2)
//deviceDriver.mSurface.makeButton(17, 5, 3, 2)
//deviceDriver.mSurface.makeButton(20, 5, 3, 2)
//deviceDriver.mSurface.makeButton(23, 5, 3, 2)
////8 knob
//deviceDriver.mSurface.makeKnob(36, 1, 4, 4)
//deviceDriver.mSurface.makeKnob(40, 1, 4, 4)
//deviceDriver.mSurface.makeKnob(44, 1, 4, 4)
//deviceDriver.mSurface.makeKnob(48, 1, 4, 4)
//deviceDriver.mSurface.makeKnob(52, 1, 4, 4)
//deviceDriver.mSurface.makeKnob(56, 1, 4, 4)
//deviceDriver.mSurface.makeKnob(60, 1, 4, 4)
//deviceDriver.mSurface.makeKnob(64, 1, 4, 4)
////8 button
//deviceDriver.mSurface.makeButton(36, 5, 4, 2)
//deviceDriver.mSurface.makeButton(40, 5, 4, 2)
//deviceDriver.mSurface.makeButton(44, 5, 4, 2)
//deviceDriver.mSurface.makeButton(48, 5, 4, 2)
//deviceDriver.mSurface.makeButton(52, 5, 4, 2)
//deviceDriver.mSurface.makeButton(56, 5, 4, 2)
//deviceDriver.mSurface.makeButton(60, 5, 4, 2)
//deviceDriver.mSurface.makeButton(64, 5, 4, 2)
//screen panel
deviceDriver.mSurface.makeBlindPanel(72, 0.0, 11, 6)
//8 fader
//deviceDriver.mSurface.makeFader(130, 1, 2, 5)
//deviceDriver.mSurface.makeFader(132, 1, 2, 5)
//deviceDriver.mSurface.makeFader(134, 1, 2, 5)
//deviceDriver.mSurface.makeFader(136, 1, 2, 5)
//deviceDriver.mSurface.makeFader(138, 1, 2, 5)
//deviceDriver.mSurface.makeFader(140, 1, 2, 5)
//deviceDriver.mSurface.makeFader(142, 1, 2, 5)
//deviceDriver.mSurface.makeFader(144, 1, 2, 5)

//3X3 button
deviceDriver.mSurface.makeBlindPanel(89, 6, 2, 1)
deviceDriver.mSurface.makeBlindPanel(92, 6, 2, 1)
deviceDriver.mSurface.makeBlindPanel(95, 6, 2, 1)

deviceDriver.mSurface.makeBlindPanel(100, 6, 2, 1)
deviceDriver.mSurface.makeBlindPanel(103, 6, 2, 1)
deviceDriver.mSurface.makeBlindPanel(106, 6, 2, 1)

deviceDriver.mSurface.makeBlindPanel(111, 6, 2, 1)
deviceDriver.mSurface.makeBlindPanel(114, 6, 2, 1)
deviceDriver.mSurface.makeBlindPanel(117, 6, 2, 1)
//8 pad
deviceDriver.mSurface.makeBlindPanel(88, 1, 4, 4)
deviceDriver.mSurface.makeBlindPanel(93, 1, 4, 4)
deviceDriver.mSurface.makeBlindPanel(98, 1, 4, 4)
deviceDriver.mSurface.makeBlindPanel(103, 1, 4, 4)
deviceDriver.mSurface.makeBlindPanel(108, 1, 4, 4)
deviceDriver.mSurface.makeBlindPanel(113, 1, 4, 4)
deviceDriver.mSurface.makeBlindPanel(118, 1, 4, 4)
deviceDriver.mSurface.makeBlindPanel(123, 1, 4, 4)

/*deviceDriver.mSurface.makePushEncoder(0, 2, 6, 6)*/